package com.cloudfast.config.decrypt;

import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;

import com.cloudfast.common.decode.DecodeUtils;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.boot.env.OriginTrackedMapPropertySource;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.Environment;
import org.springframework.core.env.MapPropertySource;
import org.springframework.core.env.MutablePropertySources;
import org.springframework.core.env.PropertySource;

import com.cloudfast.common.Constant;


/**
 * yml 解密
 *
 * @author liuyw
 * @解密spring配置文件 加密方式：DecryptUtil.aesEncrypt(明文,密钥) 配置文件使用方式：用UniEnc[密文]替换明文
 * 解密过程：从环境变量中DecryptKey获取密钥
 */
@Configuration
@SuppressWarnings({"rawtypes", "unchecked"})
public class EnvironmentContext implements EnvironmentAware, BeanFactoryPostProcessor, Ordered {

    private ConfigurableEnvironment environment;

    private Map<String, Object> decryptMap = new HashMap<>();
    private static final Map<String, String> cacheMap = new HashMap<>();


    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
        MutablePropertySources propSources = environment.getPropertySources();
        StreamSupport.stream(propSources.spliterator(), false)
                .filter(ps -> ps instanceof OriginTrackedMapPropertySource).collect(Collectors.toList())
                .forEach(ps -> convertPropertySource((PropertySource<Map>) ps));
        if (decryptMap.size() > 0) {
            MapPropertySource mapPropertySource = new MapPropertySource(Constant.ASE_ENVIRONMENT_PREFIX + Constant.ASE_ENVIRONMENT_SUFFIX, decryptMap);
            propSources.addFirst(mapPropertySource);
        }
    }

    @Override
    public void setEnvironment(Environment environment) {
        this.environment = (ConfigurableEnvironment) environment;
    }

    /**
     * 解密相关属性
     *
     * @param ps 配置文件对象
     */
    private void convertPropertySource(PropertySource<Map> ps) {
        Map source = ps.getSource();
        source.forEach((k, v) -> {
            String value = String.valueOf(v);
            cacheMap.put(k.toString(), value.trim());
            decryptMap.put(k.toString(), DecodeUtils.decodeEnvironment(value.trim()));
        });
    }

    @Override
    public int getOrder() {
        return Ordered.LOWEST_PRECEDENCE;
    }

    public static String getValue(String key) {
        return cacheMap.get(key);
    }
}
